/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.kimstore.utilities;

import com.kimstore.dao.GenericJpaDao;
import com.kimstore.dao.impl.GenericJpaDaoImpl;
import com.kimstore.factory.DaoFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import org.jdesktop.swingx.JXSearchField;

/**
 *
 * @author Administrator
 */
public class PaginateSearchAndFilter<T> {

    private GenericJpaDaoImpl dao;
    private QueryElements queryElements;
    private ArrayList<JComboBox> filterComboBoxList = new ArrayList<JComboBox>();
    private ArrayList<Integer> filterColumnsList = new ArrayList<Integer>();
    private ArrayList<String> filterVariableList = new ArrayList<String>();
    private JXSearchField searchField;
    private int searchColumn;
    private JFormattedTextField resultsPerPageField;
    private HashMap<Integer, String> columns = new HashMap<Integer, String>();
    private ArrayList<Integer> unsortableColumnsList = new ArrayList<Integer>();
    private JLabel pagesLabel;
    private int resultsPerPage = 3;
    private long totalPages = 0;
    private long currentPage = 1;
    private Integer currColSort = null;
    private Integer prevColSort = null;
    private boolean toggle = false;
    private JButton nextButton;
    private JButton prevButton;

    public PaginateSearchAndFilter(String className, String classVariable) {
        this.queryElements = new QueryElements(className, classVariable);
    }

    public ArrayList<T> search() {
        if (!queryElements.getAttributes().isEmpty()) {
            queryElements.getAttributes().clear();
            queryElements.getVariables().clear();
            queryElements.getParameters().clear();
        }
        for (int i = 0; i < filterComboBoxList.size(); i++) {
            JComboBox combobox = filterComboBoxList.get(i);
            Integer columnNumber = filterColumnsList.get(i);
            String variableName = filterVariableList.get(i);
            if (!combobox.getSelectedItem().toString().trim().equals("All")) {
                String attributeName = findColumnAttribute(columnNumber);
                queryElements.getAttributes().add(attributeName);
                queryElements.getVariables().add(variableName);
                queryElements.getParameters().put(variableName, combobox.getSelectedItem().toString());
            }
        }

        if (!searchField.getText().trim().isEmpty()) {
            queryElements.setSearchAttribute(findColumnAttribute(searchColumn));
            queryElements.setSearchValue(searchField.getText().trim());
        } else {
            queryElements.setSearchAttribute(null);
            queryElements.setSearchValue(null);
        }

        String queryString = QueryBuilder.buildQuery(queryElements);
        queryElements.setQuery(queryString);

        //System.out.println("**** QUERY: " + queryString);
        Long count = dao.count(queryElements);
        this.resultsPerPage = Integer.parseInt(resultsPerPageField.getText());

        resetPages(count);
        List<T> result = dao.filter(queryElements, (currentPage - 1) * resultsPerPage, resultsPerPage);

        return new ArrayList<>(result);
        /*
         if (orders != null) {
         if (!orders.isEmpty()) {
         populateOrdersTable(orders);
         } else {
         DefaultTableModel model = (DefaultTableModel) table.getModel();
         model.setRowCount(0);
         pagesLabel.setText("Page 0/0");
         }
         } else {
         DefaultTableModel model = (DefaultTableModel) table.getModel();
         model.setRowCount(0);
         pagesLabel.setText("Page 0/0");
         }
         * */
    }

    public boolean isColumnSortable(Integer columnNumber) {
        if (unsortableColumnsList.contains(columnNumber)) {
            return false;
        } else {
            return true;
        }
    }

    public void resetPages(Long count) {
        currentPage = 1;
        totalPages = count / resultsPerPage;
        if (count % resultsPerPage != 0) {
            totalPages++;
        }
        System.out.println(totalPages);
        if (count == 0) {
            pagesLabel.setText("No results found.");
            nextButton.setEnabled(false);
            prevButton.setEnabled(false);
        } else {
            pagesLabel.setText("Page " + currentPage + "/" + totalPages);
            prevButton.setEnabled(false);
            if (currentPage != totalPages) {
                nextButton.setEnabled(true);
            } else {
                nextButton.setEnabled(false);
            }
        }
    }

    private void updatePageButtons() {
        if (currentPage == totalPages) {
            nextButton.setEnabled(false);
        } else {
            nextButton.setEnabled(true);
        }
        if (currentPage == 1) {
            prevButton.setEnabled(false);
        } else {
            prevButton.setEnabled(true);
        }
    }

    public ArrayList<T> nextPage() {
        if (currentPage < totalPages) {
            System.out.println("IN HEREEEEEE");
            currentPage++;
            pagesLabel.setText("Page " + currentPage + "/" + totalPages);
            updatePageButtons();
            //System.out.println("Current Page: " + currentPage);
            //System.out.println("Results per Page: " + resultsPerPage);
            //System.out.println("Query Elements: " + queryElements.getClassName());
            List<T> result = dao.filter(queryElements, (currentPage - 1) * resultsPerPage, resultsPerPage);
            //System.out.println(result);
            return new ArrayList<>(result);
        }
        return null;
    }

    public ArrayList<T> previousPage() {
        if (currentPage > 1) {
            currentPage--;
            pagesLabel.setText("Page " + currentPage + "/" + totalPages);
            updatePageButtons();
            List<T> result = dao.filter(queryElements, (currentPage - 1) * resultsPerPage, resultsPerPage);
            return new ArrayList<>(result);
        }
        return null;
    }

    public ArrayList<T> sort(Integer selectedColumn) {
        if (currColSort != null) {
            prevColSort = currColSort;
        }

        if (selectedColumn != null) {
            currColSort = selectedColumn;
            queryElements.setOrderByColumn(findColumnAttribute(currColSort));

            if (currColSort == prevColSort) {
                if (!toggle) {
                    queryElements.setOrderByOrder(QueryBuilder.DESC);
                    toggle = true;
                } else {
                    queryElements.setOrderByOrder(QueryBuilder.ASC);
                    toggle = false;
                }
            } else {
                queryElements.setOrderByOrder(QueryBuilder.ASC);
                toggle = false;
            }
        }
        //System.out.println("ORDER: " + queryElements.getOrderByColumn());
        ArrayList<T> result = search();
        return result;
    }

    private String findColumnAttribute(Integer columnNumber) {
        return columns.get(columnNumber);
    }

    /*
     public void bindElements() {
     table.setRowSorter(new CustomTableRowSorter(table.getRowSorter().getModel()) {
     @Override
            
        
     });
     searchButton.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
     search();
     }
     });
     nextButton.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
     nextPage();
     }
     });

     prevButton.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
     previousPage();
     }
     });

     }
     * */
    public void addColumn(Integer columnNumber, String columnName) {
        columns.put(columnNumber, columnName);
    }

    public void addColumn(Integer columnNumber, String columnName, boolean sortable) {
        columns.put(columnNumber, columnName);
        if (!sortable) {
            unsortableColumnsList.add(columnNumber);
        }
    }

    public void addFilter(JComboBox filterComboBox, int filterColumns, String filterVariableName) {
        filterComboBoxList.add(filterComboBox);
        filterColumnsList.add(filterColumns);
        filterVariableList.add(filterVariableName);
    }

    public GenericJpaDaoImpl getDao() {
        return dao;
    }

    public void setDao(GenericJpaDaoImpl dao) {
        this.dao = dao;
    }

    public QueryElements getQueryElements() {
        return queryElements;
    }

    public void setQueryElements(QueryElements queryElements) {
        this.queryElements = queryElements;
    }

    public JLabel getPagesLabel() {
        return pagesLabel;
    }

    public void setPagesLabel(JLabel pagesLabel) {
        this.pagesLabel = pagesLabel;
    }

    public int getResultsPerPage() {
        return resultsPerPage;
    }

    public void setResultsPerPage(int resultsPerPage) {
        this.resultsPerPage = resultsPerPage;
    }

    public long getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(long totalPages) {
        this.totalPages = totalPages;
    }

    public long getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(long currentPage) {
        this.currentPage = currentPage;
    }

    public ArrayList<JComboBox> getFilterComboBoxList() {
        return filterComboBoxList;
    }

    public void setFilterComboBoxList(ArrayList<JComboBox> filterComboBoxList) {
        this.filterComboBoxList = filterComboBoxList;
    }

    public ArrayList<Integer> getFilterColumnsList() {
        return filterColumnsList;
    }

    public void setFilterColumnsList(ArrayList<Integer> filterColumnsList) {
        this.filterColumnsList = filterColumnsList;
    }

    public ArrayList<String> getFilterVariableList() {
        return filterVariableList;
    }

    public void setFilterVariableList(ArrayList<String> filterVariableList) {
        this.filterVariableList = filterVariableList;
    }

    public JXSearchField getSearchField() {
        return searchField;
    }

    public void setSearchField(JXSearchField searchField, String promptText) {
        this.searchField = searchField;
        this.searchField.setPrompt(promptText);
    }

    public int getSearchColumn() {
        return searchColumn;
    }

    public void setSearchColumn(int searchColumn) {
        this.searchColumn = searchColumn;
    }

    public JFormattedTextField getResultsPerPageField() {
        return resultsPerPageField;
    }

    public void setResultsPerPageField(JFormattedTextField resultsPerPageField) {
        this.resultsPerPageField = resultsPerPageField;
    }

    public HashMap<Integer, String> getColumns() {
        return columns;
    }

    public void setColumns(HashMap<Integer, String> columns) {
        this.columns = columns;
    }

    public Integer getCurrColSort() {
        return currColSort;
    }

    public void setCurrColSort(Integer currColSort) {
        this.currColSort = currColSort;
    }

    public Integer getPrevColSort() {
        return prevColSort;
    }

    public void setPrevColSort(Integer prevColSort) {
        this.prevColSort = prevColSort;
    }

    public boolean isToggle() {
        return toggle;
    }

    public void setToggle(boolean toggle) {
        this.toggle = toggle;
    }

    public ArrayList<Integer> getUnsortableColumnsList() {
        return unsortableColumnsList;
    }

    public void setUnsortableColumnsList(ArrayList<Integer> unsortableColumnsList) {
        this.unsortableColumnsList = unsortableColumnsList;
    }

    public JButton getNextButton() {
        return nextButton;
    }

    public void setNextButton(JButton nextButton) {
        this.nextButton = nextButton;
    }

    public JButton getPrevButton() {
        return prevButton;
    }

    public void setPrevButton(JButton prevButton) {
        this.prevButton = prevButton;
    }
}
